<?php


namespace app\live\controller\v1;


use app\aliyun\controller\AliyunLive;
use app\aliyun\controller\AliyunRtc;
use app\chat\LiveMessage;
use app\common\cachemodel\Goods;
use app\common\cachemodel\live\LiveAnchorInfo;
use app\common\cachemodel\live\LiveAnswerAstroRecord;
use app\common\cachemodel\live\LiveAnswerDiceRecord;
use app\common\cachemodel\live\LiveAnswerTarotRecord;
use app\common\cachemodel\live\LiveAwardAcitveRecord;
use app\common\cachemodel\live\LiveBroadcastPreview;
use app\common\cachemodel\live\LiveCouponActiveRecord;
use app\common\cachemodel\live\LiveDisableSendMsg;
use app\common\cachemodel\live\LiveGoodsActivity;
use app\common\cachemodel\live\LiveRecordingInfo;
use app\common\cachemodel\live\LiveRecordUserHot;
use app\common\cachemodel\live\LiveSignHotDay;
use app\common\cachemodel\live\LiveUserContribution;
use app\common\cachemodel\MallGoodsAttr;
use app\common\lib\exception\ApiException;
use app\common\lib\Util;
use app\common\model\User;
use app\live\controller\LiveAuth;
use think\Cache;
use think\Db;
use think\response\Json;
use XznsTools\cache\CacheManage;

class LiveActive extends LiveAuth
{
    /**
     * @return \think\response\Json
     * @throws \Exception
     */
    public function getLiveRoomInfo()
    {
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);
        $record = (new LiveRecordingInfo())->getInfoById($liveRecordId, ['status', 'title', 'content', 'live_type']);

        if ($record['status'] == 1)
        {   // 继续直播
            if ($record['live_type'] == 3)
            {   // 当前为录播
                return show(config('code.error'), '录播中,请先关闭录播再发起直播～');
            }
            $title = $record['title'] ?? '';
            $liveContent = $record['content'] ?? '';
        } else
        {   // 开播
            //获取预告信息
            $preview = (new LiveBroadcastPreview())->getNewestPreview();

            if ($preview && $preview['live_id'] != $this->liveInfo['live_id'])
            {
                $preview = null;
            }

            $title = $preview['broadcast_title'] ?? '';
            $liveContent = $preview['broadcast_content'] ?? '';
        }

        $data = [
            'live_id' => $this->liveInfo['live_id'],
            'avatar' => $this->liveInfo['avatar'],
            'nickname' => $this->liveInfo['name'],
            'title' => $title,
            'live_content' => $liveContent,
            'status' => $record['status'] == 1 ? 1 : 0,
            'List_rules' => (new LiveAnchorInfo())->getListRules(),
            'beauty_config' => $this->liveInfo['beauty_config'] ?? '',
        ];
        if ($liveRecordId)
        {
            $astroInfo = (new LiveAnswerAstroRecord())->getLiveAnswerProgressInfo($liveRecordId, 1);
            $diceInfo = (new LiveAnswerDiceRecord())->getLiveAnswerProgressInfo($liveRecordId, 1);
            $tarotInfo = (new LiveAnswerTarotRecord())->getLiveAnswerProgressInfo($liveRecordId, 1);
            if ($astroInfo)
            {
                $data['answer_btn'][] = $astroInfo;
            }
            if ($diceInfo)
            {
                $data['answer_btn'][] = $diceInfo;
            }
            if ($tarotInfo)
            {
                $data['answer_btn'][] = $tarotInfo;
            }
        }
        return show(config('code.success'), '获取成功', $data);
    }

    /**
     * 开启直播
     */
    public function liveStart()
    {
        $title = input('title/s', '');
        $liveContent = input('live_content/s', '');
        $cameraStatus = input('camera_status/d', 1);
        $radioStatus = input('radio_status/d', 1);

        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);
        $record = (new LiveRecordingInfo())->getInfoById($liveRecordId, ['status', 'push_url']);
        if ($record['status'] == 1)
        {   // 继续直播
            $cameraRadioStatus = Cache::get('live:camera_radio_status' . $this->liveInfo['live_id']);

            if (empty($cameraRadioStatus)
                || !isset($cameraRadioStatus['camera_status'], $cameraRadioStatus['radio_status'])
                || $cameraRadioStatus['camera_status'] != $cameraStatus
                || $cameraRadioStatus['radio_status'] != $radioStatus)
            {   // 摄像头或麦克风 开启状态 更新
                LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ALL, $this->liveInfo['live_id'], $this->liveInfo['live_id'])
                    , LiveMessage::MSG_TYPE_CHANGE_CAMERA_RADIO, [
                        'camera_status' => $cameraStatus,
                        'radio_status' => $radioStatus,
                    ]);

                Cache::set('live:camera_radio_status' . $this->liveInfo['live_id'], [
                    'camera_status' => $cameraStatus,
                    'radio_status' => $radioStatus,
                ], 86400 * 2);
            }

            return show(config('code.success'), '请求成功', [
                'push_data_url' => $record['push_url'],
                'live_record_id' => $liveRecordId,
            ]);
        }

        if (empty($title))
        {
            return show(config('code.error'), '直播标题不能为空！');
        }
        if (empty($liveContent))
        {
            return show(config('code.error'), '直播内容不能为空！');
        }
        if (mb_strlen($title) > 12)
        {
            return show(config('code.error'), '直播标题不能不能超过15字！');
        }
        if (mb_strlen($liveContent) > 48)
        {
            return show(config('code.error'), '直播内容不能不能超过50字！');
        }

        // 初始化用户热度表
        if (!(new LiveRecordUserHot())->createUserHotTable($this->liveInfo['live_id']))
        {
            return show(config('code.error'), '服务异常，请稍后再试～');
        }

        $data = [
            'live_id' => $this->liveInfo['live_id'],
            'status' => 1,
            'title' => $title,
            'content' => $liveContent,
            'live_start_time' => $this->request->time(),
        ];

        $liveRecordId = (new LiveRecordingInfo())->addLive($data);

        //直播地址
        $liveUrl = (new AliyunLive())->createLive($this->liveInfo['live_id'], $liveRecordId);

        (new LiveRecordingInfo())->updateData($liveRecordId, [
            'push_url' => $liveUrl['push_url'],
            'pull_url' => json_encode($liveUrl['pull_url'], JSON_UNESCAPED_UNICODE),
            'pull_url_definition_list' => json_encode($liveUrl['pull_url_definition_list'], JSON_UNESCAPED_UNICODE),
        ]);

        if ($liveRecordId)
        {
            Cache::set('live:camera_radio_status' . $this->liveInfo['live_id'], [
                'camera_status' => $cameraStatus,
                'radio_status' => $radioStatus,
            ], 86400 * 2);

            Util::queuePush('live_subscribe_send', ['live_info' => $this->liveInfo], 300);

            return show(config('code.success'), '请求成功', [
                'push_data_url' => $liveUrl['push_url'],
                'live_record_id' => $liveRecordId,
            ]);
        } else
        {
            return show(config('code.error'), '服务异常');
        }
    }

    /**
     * 停止直播
     */
    public function liveStop()
    {
        $liveRecordId = input('live_record_id/d', 0);

        if (!$liveRecordId)
        {
            return show(config('code.error'), '请求异常');
        }

        $record = (new LiveRecordingInfo())->getInfoById($liveRecordId, ['live_id', 'status', 'live_start_time']);

        if ($record && $record['live_id'] == $this->liveInfo['live_id'])
        {
            if ($record['status'] == 1)
            {
                $liveDuration = ceil(($this->request->time() - $record['live_start_time']) / 60);// 直播时长 分钟

                $res = (new LiveRecordingInfo())->updateData($liveRecordId, [
                    'status' => 2,
                    'live_duration' => $liveDuration,
                    'close_time' => $this->request->time(),
                    'close_use_type' => 1,
                    'close_uid' => 0,
                ]);
                // 删除直播记录列表缓存
                CacheManage::getInstance()->setCacheConfig('live.live_recording', $this->liveInfo['live_id'])->rmCache('list');

                if ($res)
                {
                    $taskId = Cache::get('live:startMPUTask:taskId:' . $this->liveInfo['live_id'], false);
                    if ($taskId)
                    {
                        // 关闭旧的        旁路直播
                        $result = (new AliyunRtc())->stopMPUTask($taskId);
                        if ($result['code'] !== 200)
                        {
                            return show(config('code.error'), $result['msg']);
                        }
                    }
                    // 向用户发送关播消息
                    LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ALL, $this->liveInfo['live_id'], $this->liveInfo['live_id']), LiveMessage::MSG_TYPE_LIVE_STATUS, 1);
                    // 删除用户发送消息记录缓存
                    $redis = CacheManage::getInstance()->redisHandler;
                    $redis->del('live:send:msg:record:' . $this->liveInfo['live_id']);

                    return show(config('code.success'), '直播已结束', [
                        'target' => 'local',
                        'link' => 'liver_page?page=live_detail&id=' . $liveRecordId,
                    ]);
                } else
                {
                    return show(config('code.error'), '服务异常');
                }

            } else
            {
                return show(config('code.success'), '直播已结束', [
                    'target' => 'local',
                    'link' => 'liver_page?page=live_detail&id=' . $liveRecordId,
                ]);
            }
        }

        return show(config('code.error'), '直播不存在');
    }

    /**
     * 禁言
     */
    public function disableSendMsg()
    {
        $messageId = input('message_id/d', 0);
        $liveRecordId = input('live_record_id/d', 0);

        $messageInfo = Db::table('live_data.live_message_' . $liveRecordId)->where('id', $messageId)->find();

        if ($messageInfo['live_id'] != $this->liveInfo['live_id'])
        {
            return show(config('code.error'), '服务异常，禁言失败');
        }

        $data = [
            'message_id' => $messageId,
            'live_id' => $this->liveInfo['live_id'],
            'live_record_id' => $liveRecordId,
            'uid' => $messageInfo['uid'],
            'status' => 1,
            'create_time' => $this->request->time(),
            'update_time' => $this->request->time(),
        ];

        $res = (new LiveDisableSendMsg())->userDisableSendMsg($this->liveInfo['live_id'], $liveRecordId, $messageInfo['uid'], $data);

        if ($res)
        {
            return show(config('code.success'), '禁言成功！');
        } else
        {
            return show(config('code.error'), '服务异常，禁言失败');
        }
    }

    /**
     * 获取抽奖或赠送列表
     */
    public function getAwardOrGiveList()
    {
        $type = input('type/d', 1);

        if ($type === 1)
        {
            $resData = (new LiveAwardAcitveRecord())->getRecordLists($this->liveInfo['live_id']);
        } else
        {
            $resData = (new LiveCouponActiveRecord())->getRecordLists($this->liveInfo['live_id']);
        }

        return show(config('code.success'), '请求成功', $resData);
    }

    /**
     * 直播间贡献总榜
     * @return Json
     * @throws ApiException
     */
    public function getConRankingList()
    {
        $page = input('page/d', 1);
        $limit = input('limit/d', 10);

        if ($limit < 1 || $limit > 50)
        {
            $limit = 10;
        }

        if ($page < 1)
        {
            $page = 1;
        }

        $pageData = (new LiveUserContribution())->getContributionRanking($this->liveInfo['live_id'], $page, $limit);

        $resData = [];
        foreach ($pageData['data'] as $uid => $rankingInfoItem)
        {
            $userInfo = current((new User())->batchGetUserInfo([$uid]));
            if ($userInfo)
            {
                $resData[] = [
                    'avatar' => $userInfo['avatar'],
                    'nickname' => $userInfo['nickname'],
                    'ranking' => $rankingInfoItem['ranking'],
                    'desc' => "贡献值：{$rankingInfoItem['contribution_value']}",
                    'is_online' => LiveMessage::getUidIsOnline($this->liveInfo['live_id'], $uid) ? 1 : 0,
                ];
            }
        }

        $pageData['data'] = $resData;

        return show(config('code.success'), '请求成功', $pageData);
    }

    /**
     * 获取热度日榜
     */
    public function getHotDayRankingList()
    {
        // 获取最新的直播记录ID
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);

        $dayRankingList = (new LiveSignHotDay())->getDaySignList($this->liveInfo['live_id'], $liveRecordId, date('Ymd'));

        for ($i = 1; $i < 13; $i++)
        {
            if (!isset($dayRankingList[$i]))
            {
                $dayRankingList[$i] = 0;
            }
        }

        arsort($dayRankingList);

        $resData = [];
        foreach ($dayRankingList as $sign => $hotNum)
        {
            if ($sign > 0)
            {
                $resData[] = [
                    'sign' => $sign,
                    'hot_num' => $hotNum . '热度',
                ];
            }
        }

        return show(config('code.success'), '请求成功', $resData);
    }

    /**
     * 获取在线时长和观看人数
     */
    public function getOnlineDurationAndNum()
    {
        // 获取最新的直播记录ID
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);
        if (!$liveRecordId)
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }
        $liveRecordInfo = (new LiveRecordingInfo())->getInfoById($liveRecordId, ['live_start_time', 'content']);
        $liveBroadcastPreview = (new LiveBroadcastPreview())->where('live_start_time', '>', $this->request->time())->order('live_start_time asc')->find();

        return show(config('code.success'), '请求成功', [
            'duration' => Sec2Time($this->request->time() - $liveRecordInfo['live_start_time']),
            'total_num' => LiveMessage::getClientIdCountByGroup($this->liveInfo['live_id'] . '_app_user_group') . "人观看",//获取在线人数
            'live_advance' => $liveBroadcastPreview['broadcast_content'] ?? '',
            'live_content' => $liveRecordInfo['content'],
            'avatar' => $this->liveInfo['avatar'],
            'nickname' => $this->liveInfo['name'],
            'intro' => $this->liveInfo['intro'] ?? '',
        ]);
    }

    /**
     * 获取直播间推荐商品
     * @return Json
     * @throws \Exception
     */
    public function getLiveGoods()
    {
        $type = input('type/d', 1);
        if (!in_array($type, [1, 2], true))
        {
            $type = 1;
        }
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);
        $liveGoodsModel = new LiveGoodsActivity();
        $goods = $liveGoodsModel->getAnchorGoods($this->liveInfo['live_id'], $type, true);
        $data = $liveGoodsModel->resetGoods($goods, $this->liveInfo['live_id'], $liveRecordId, 2);
        return show(config('code.success'), '获取成功', $data);
    }

    /**
     * 直播间推荐商品
     */
    public function recommendGoods()
    {
        $id = input('id/d', 0);

        if (empty($id))
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);

        $liveGoodsModel = new LiveGoodsActivity();
        $goodInfo = $liveGoodsModel->getInfoById($id);
        //缓存当前推荐的商品
        Cache::set('live_recommend_goods_' . $liveRecordId, $goodInfo['category'] . '-' . $id, 86400);

        $mallGoodsAttrModel = new MallGoodsAttr();
        $explode = explode(',', $goodInfo['gids']);
        sort($explode);
        $gid = current($explode);
        if ($goodInfo['category'] == 2)
        {
            $tmp = $mallGoodsAttrModel->batGetInfo([$gid], ['now_price']);
            $orPrice = sprintf('%.2f', current($tmp)['now_price']);
            $nowPrice = sprintf('%.2f', $goodInfo['attr']);
            $btnTxt = '立即购买';
        } else
        {
            if ($goodInfo['attr'] != 1)
            {
                $discount = (new Util())->numberChinese($goodInfo['attr'] * 10);
                $btnTxt = "特惠{$discount}折";
            } else
            {
                $btnTxt = '立即购买';
            }
        }

        (new Goods())->goodsTargetLink((int)$goodInfo['gtype'], $goodInfo['link']);
        // 推送给所有人  此处需要排除主播
        LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ALL, $this->liveInfo['live_id'], $this->liveInfo['live_id']), LiveMessage::MSG_TYPE_POP_RECOMMEND, [
            'id' => $id,
            'title' => $goodInfo['name'],
            'img' => $goodInfo['img'],
            'name' => $goodInfo['des'],
            'original_price_des' => $orPrice ?? '',
            'now_price' => $nowPrice ?? '',
            'btn_info' => [
                'name' => $btnTxt,
                'target' => $goodInfo['target'],
                'link' => $goodInfo['link'] . '&is_jump_intro=1&live_id=' . $this->liveInfo['live_id'] . '&live_record_id=' . $liveRecordId,
            ],
        ]);
        // LiveMessage::who(LiveMessage::WHO_TYPE_LIVER, $this->liveInfo['live_id'], $this->liveInfo['live_id']) 发送给主播

        return show(config('code.success'), '推荐成功');
    }

    /**
     * 直播间推荐商品 关闭
     */
    public function closeRecommendGoods()
    {
        $liveRecordId = (new LiveRecordingInfo())->getNewestRecord($this->liveInfo['live_id']);

        Cache::rm('live_recommend_goods_' . $liveRecordId);

        // 推送给所有人  此处需要排除主播
        LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ALL, $this->liveInfo['live_id'], $this->liveInfo['live_id']), LiveMessage::MSG_TYPE_CLOSE_RECOMMEND_GOODS, 1);

        return show(config('code.success'), '关闭推荐成功');
    }

    /**
     * 摄像头和麦克风开启状态更新
     */
    public function changeCameraRadio()
    {
        $cameraStatus = input('camera_status/d', 1);
        $radioStatus = input('radio_status/d', 1);

        LiveMessage::sendMsg(LiveMessage::who(LiveMessage::WHO_TYPE_ALL, $this->liveInfo['live_id'], $this->liveInfo['live_id'])
            , LiveMessage::MSG_TYPE_CHANGE_CAMERA_RADIO, [
                'camera_status' => $cameraStatus,
                'radio_status' => $radioStatus,
            ]);

        Cache::set('live:camera_radio_status' . $this->liveInfo['live_id'], [
            'camera_status' => $cameraStatus,
            'radio_status' => $radioStatus,
        ], 86400 * 2);

        return show(config('code.success'), '状态更新成功');
    }

    /**
     * 获取抽奖记录详情信息
     */
    public function getAwardRecordInfo()
    {
        $id = input('id/d', 0);

        if (empty($id))
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }

        $data = (new LiveAwardAcitveRecord())->getAwardActiveRecordInfo($this->liveInfo['live_id'], $id);

        if ($data)
        {
            return show(config('code.success'), '请求成功', $data);
        } else
        {
            return show(config('code.error'), '抽奖记录不存在～');
        }
    }

    /**
     * 获取优惠券赠送记录详情
     */
    public function getCouponSendRecordInfo()
    {
        $id = input('id/d', 0);

        if (empty($id))
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }

        $data = (new LiveCouponActiveRecord())->getRecordDetail($this->liveInfo['live_id'], $id);

        if ($data)
        {
            return show(config('code.success'), '请求成功', $data);
        } else
        {
            return show(config('code.error'), '赠送记录不存在～');
        }
    }

    /**
     * 获取直播记录详情
     */
    public function getLiveRecordDetail()
    {
        $id = input('id/d');

        if (empty($id))
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }

        $data = (new LiveRecordingInfo())->getRecordDetail($this->liveInfo['live_id'], $id);

        if ($data)
        {
            return show(config('code.success'), '请求成功', $data);
        } else
        {
            return show(config('code.error'), '直播记录不存在～');
        }
    }

    /**
     * 获取数据总览详情
     */
    public function getAllDetail()
    {
        $startTime = trim(input('start_time/s', ''));
        $endTime = trim(input('end_time/s', ''));

        $startTime .= ' 00:00:00';
        $endTime .= ' 23:59:59';

        $st = strtotime($startTime);
        $et = strtotime($endTime);

        if (empty($startTime) || empty($endTime) || date('Y-m-d H:i:s', $st) !== $startTime || date('Y-m-d H:i:s', $et) != $endTime)
        {
            return show(config('code.error'), '请求异常，请稍后再试～');
        }

        if ($st >= $et)
        {
            return show(config('code.error'), '结束必须大于开始时间');
        }

        $data = (new LiveRecordingInfo())->getTimeRangeDetail($this->liveInfo['live_id'], $startTime, $endTime);

        if ($data)
        {
            return show(config('code.success'), '请求成功', $data);
        } else
        {
            return show(config('code.error'), '直播记录不存在～');
        }
    }
}
